﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace myMapObj
{
    class SEGV
    {

        #region 字段
        /// <summary>
        /// SEGV文件完整路径
        /// </summary>
        string filePath;
        /// <summary>
        /// 属性文件路径
        /// </summary>
        string attrFilePath;
        /// <summary>
        /// 空间数据类型
        /// </summary>
        moGeometryTypeConstant _GeometryType;
        int _GeometryTypeID; //表示空间数据类型的整数
        double _MinX = double.MaxValue, _MaxX = double.MinValue;
        double _MinY = double.MaxValue, _MaxY = double.MinValue;
        /// <summary>
        /// 要素个数
        /// </summary>
        int _FeatureCount;

        List<moPoint> _Points;
        List<moMultiPolyline> _MultiPolylines;
        List<moMultiPolygon> _MultiPolygons;
        #endregion

        #region 属性
        /// <summary>
        /// 要素名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 文件完整路径
        /// </summary>
        public string FilePath
        {
            get { return filePath; }
            set { filePath = value; }
        }
        /// <summary>
        /// 属性文件路径
        /// </summary>
        public string AttrFilePath
        {
            get { return attrFilePath; }
        }
        public double MinX
        {
            get { return _MinX; }
        }
        public double MinY
        {
            get { return _MinY; }
        }
        public double MaxX
        {
            get { return _MaxX; }
        }
        public double MaxY
        {
            get { return _MaxY; }
        }
        /// <summary>
        /// 要素个数
        /// </summary>
        public double FeatureCount
        {
            get { return _FeatureCount; }
        }
        /// <summary>
        /// 要素类型
        /// </summary>
        public moGeometryTypeConstant SpaceDataType
        {
            get { return _GeometryType; }
        }
        #endregion

        #region 构造函数
        /// <summary>
        /// 基于文件路径的构造函数
        /// </summary>
        /// <param name="path">文件路径</param>
        public SEGV(string path)
        {
            if (Path.GetExtension(path) != ".segv")
                throw new IOException("文件拓展名不正确！");
            this.filePath = path;
            this.Name = Path.GetFileNameWithoutExtension(path);
            //this.attrFilePath = Path.GetDirectoryName(path) + "\\" + Name + ".mdb";
            using (StreamReader sr = new StreamReader(new FileStream(path, FileMode.Open)))
            {
                string strLine = sr.ReadLine();  //读文件头
                string[] data = strLine.Split(' ');
                _GeometryTypeID = int.Parse(data[0]);
                _FeatureCount = int.Parse(data[1]);
                strLine = sr.ReadLine();  //读文件头
                data = strLine.Split(' ');
                _MinX = Double.Parse(data[0]);
                _MaxX = Double.Parse(data[1]);
                _MinY = Double.Parse(data[2]);
                _MaxY = Double.Parse(data[3]);
                switch (_GeometryTypeID)
                {
                    case 0:
                        _GeometryType = moGeometryTypeConstant.Point;
                        ReadPointSEgv(sr);
                        break;
                    case 1:
                        _GeometryType = moGeometryTypeConstant.MultiPolyline;
                        ReadMultiPolylineSEgv(sr);
                        break;
                    case 2:
                        _GeometryType = moGeometryTypeConstant.MultiPolygon;
                        ReadMultiPolygonSEgv(sr);
                        break;
                }
            }
        }
        #endregion

        #region 私有函数

        private int GetGeometryTypeID(moGeometryTypeConstant GeometryType)
        {
            int id = -1;
            switch (_GeometryType)
            {
                case moGeometryTypeConstant.Point:
                    id = 0;
                    break;
                case moGeometryTypeConstant.MultiPolyline:
                    id = 1;
                    break;
                case moGeometryTypeConstant.MultiPolygon:
                    id = 2;
                    break;
            }
            return id;
        }

        private void ReadPointSEgv(StreamReader sr)
        {
            string strLine;
            string[] data;
            _Points = new List<moPoint>();
            for (int i = 0; i < _FeatureCount; i++)
            {
                strLine = sr.ReadLine();
                data = strLine.Split(' ');
                double x = Double.Parse(data[1]);
                double y = Double.Parse(data[2]);
                _Points.Add(new moPoint(x, y));
            }
        }

        private void ReadMultiPolylineSEgv(StreamReader sr)
        {
            _MultiPolylines = new List<moMultiPolyline>();
            for (int i = 0; i < _FeatureCount; i++)
                _MultiPolylines.Add(new moMultiPolyline(sr));
        }

        private void ReadMultiPolygonSEgv(StreamReader sr)
        {
            _MultiPolygons = new List<moMultiPolygon>();
            for (int i = 0; i < _FeatureCount; i++)
                _MultiPolygons.Add(new moMultiPolygon(sr));
        }

        private void WritePointSEgv(StreamWriter sw)
        {
            string strLine;
            for (int i = 0; i < _FeatureCount; i++)
            {
                strLine = _Points[i].X.ToString() + " " + _Points[i].Y.ToString();
                sw.WriteLine(strLine);
            }
        }
        private void WriteMultiPolylineSEgv(StreamWriter sw)
        {
            for (int i = 0; i < _FeatureCount; i++)
                _MultiPolylines[i].WriteSEgv(sw);
        }

        private void WriteMultiPolygonSEgv(StreamWriter sw)
        {
            for (int i = 0; i < _FeatureCount; i++)
                _MultiPolygons[i].WriteSEgv(sw);
        }
        #endregion

        #region 方法

        public void Save(string saveFilePath)
        {
            using (StreamWriter sw = new StreamWriter(saveFilePath, false))
            {
                string title = _GeometryTypeID.ToString() + " " + _FeatureCount.ToString();  //文件头
                sw.WriteLine(title);
                string extent = _MinX.ToString() + " " + _MaxX.ToString()
                              + " " + _MinY.ToString() + " " + _MaxY.ToString();
                sw.WriteLine(extent);
                switch (_GeometryTypeID)
                {
                    case 0:
                        WritePointSEgv(sw);
                        break;
                    case 1:
                        WriteMultiPolylineSEgv(sw);
                        break;
                    case 2:
                        WriteMultiPolygonSEgv(sw);
                        break;
                }
            }
        }


        /// <summary>
        /// 在指定路径下创建指定类型的空白SEGV文件
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <param name="spaceDataType">要素类型</param>
        public void CreateEmptySEgv(string path, moGeometryTypeConstant GeometryType)
        {
            using (StreamWriter sw = new StreamWriter(path, false))
            {
                string title = GetGeometryTypeID(GeometryType).ToString() + " 0";  //文件头
                sw.WriteLine(title);
                string extent = "10000000 -10000000 10000000 -10000000";
                sw.WriteLine(extent);
            }
            /*
            string mdbFilePath = Path.GetDirectoryName(path) + "\\" + Path.GetFileNameWithoutExtension(path) + ".mdb";
            ADOX.Catalog catalog = new Catalog();
            catalog.Create(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + mdbFilePath);  //此语句在数据库已经存在时会报错，待完善

            string connectString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + mdbFilePath;
            OleDbConnection cnn = new OleDbConnection(connectString);
            cnn.Open();
            OleDbCommand command = new OleDbCommand("Create Table " + Path.GetFileNameWithoutExtension(path) + "(FID integer primary key);", cnn);
            command.ExecuteNonQuery();
            cnn.Close();
            cnn.Dispose();
            */
        }

        public moGeometry[] GetGeometryFeature()
        {
            moGeometry[] sGeometries = null;
            switch (_GeometryType)
            {
                case moGeometryTypeConstant.Point:
                    sGeometries = _Points.ToArray();
                    break;
                case moGeometryTypeConstant.MultiPolyline:
                    sGeometries = _MultiPolylines.ToArray();
                    break;
                case moGeometryTypeConstant.MultiPolygon:
                    sGeometries = _MultiPolygons.ToArray();
                    break;
                default:
                    break;
            }
            return sGeometries;
        }
        #endregion
    }
}
